/*
 *  Copyright (C) 2013  Venkat Raghavan G
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  
 *  
 */

package edu.uic.cs.analyze.text;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import edu.uic.cs.analyze.commons.FileUtils;
import edu.uic.cs.analyze.commons.StringUtils;
import edu.uic.cs.analyze.text.model.Span;

// TODO: Auto-generated Javadoc
/**
 * The Class Processor.
 * 
 * @author Venkat Raghavan G
 * @version 1.0
 */
public class TextProcessor {

	protected Set<String> stopwordSet;
	protected HashMap<String, String> replaceTokenMap;
	protected HashMap<String, String> replacePhraseMap;
	private boolean STOPWORD_IGNORE_CASE = true;
	private boolean REPLACE_IGNORE_CASE = true;
	private boolean REPLACE_REGEX_COMPATIBILITY = false;

	/**
	 * Instantiates a new processor.
	 */
	public TextProcessor() {
	}

	public HashMap<String, String> getReplaceTokenMap() {
		return replaceTokenMap;
	}

	public void setReplaceTokenMap(HashMap<String, String> replaceTokenMap) {
		this.replaceTokenMap = replaceTokenMap;
	}

	public HashMap<String, String> getReplacePhraseMap() {
		return replacePhraseMap;
	}

	public void setReplacePhraseMap(HashMap<String, String> replacePhraseMap) {
		this.replacePhraseMap = replacePhraseMap;
	}

	public void setStopwordSet(Set<String> stopwordSet) {
		this.stopwordSet = stopwordSet;
	}

	public List<String> tokenizeString(String rawContent) {
		StringTokenizer st = new StringTokenizer(rawContent);
		List<String> tokens = new ArrayList<String>();
		while (st.hasMoreTokens()) {
			tokens.add(st.nextToken());
		}
		return tokens;
	}

	public Set<String> getStopwordSet() {
		return stopwordSet;
	}

	public void setStopwordFile(File stopwordFile, boolean ignoreCase) {
		this.STOPWORD_IGNORE_CASE = ignoreCase;
		this.stopwordSet = FileUtils.getFileContentAsSet(stopwordFile,
				ignoreCase);
	}

	public HashMap<String, String> getReplaceMap() {
		return replaceTokenMap;
	}

	public void setReplaceTokenFile(File replaceFile, String delimiterRegex,
			boolean ignoreCase) {
		this.REPLACE_IGNORE_CASE = ignoreCase;
		this.replaceTokenMap = FileUtils.getFileContentAsMap(replaceFile,
				delimiterRegex, ignoreCase);
	}

	public void setReplacePhraseFile(File replaceFile, String delimiterRegex,
			boolean ignoreCase, boolean regexCompatible) {
		this.REPLACE_IGNORE_CASE = ignoreCase;
		this.REPLACE_REGEX_COMPATIBILITY = regexCompatible;
		this.replacePhraseMap = FileUtils.getFileContentAsMap(replaceFile,
				delimiterRegex, ignoreCase);
		if (!REPLACE_REGEX_COMPATIBILITY) {
			HashMap<String, String> tempMap = new HashMap<String, String>();
			for (String s : this.replacePhraseMap.keySet()) {
				String value = this.replacePhraseMap.get(s);
				tempMap.put(StringUtils.escapeRegex(s), value);
			}
			this.replacePhraseMap = tempMap;
		}
	}

	public boolean getStopwordCase() {
		return this.STOPWORD_IGNORE_CASE;
	}

	public boolean getReplaceCase() {
		return this.REPLACE_IGNORE_CASE;
	}

	/**
	 * Cleans the string and removes unwanted characters. If replaceString is
	 * not null, unwanted characters are replaced with it.
	 * 
	 * @param rawcontent
	 *            the raw content
	 * @param replaceString
	 *            the replace string
	 * @return the string
	 * @throws UnsupportedEncodingException
	 *             the unsupported encoding exception
	 */
	public String cleanseContent(String rawcontent, String replaceString)
			throws UnsupportedEncodingException {
		StringBuffer sb = new StringBuffer();

		for (Character c : rawcontent.toCharArray()) {
			int cval = ((int) c);
			if (!isUnwantedLetter(cval))
				sb.append(c);
			else if (replaceString != null)
				sb.append(replaceString);
		}

		return sb.toString();

	}

	/**
	 * Checks if is unwanted letter.
	 * 
	 * @param cval
	 *            the cval
	 * @return true, if is unwanted letter
	 */
	private static boolean isUnwantedLetter(int cval) {
		if ((cval >= 127) || (cval == 0))
			return true;
		return false;
	}

	/**
	 * Removes stopwords. Uses the stopword file if customStopwordSet set is
	 * null.
	 * 
	 * @param rawContent
	 * @param customStopwordSet
	 * @return
	 */
	public String removeStopwords(String rawContent,
			Set<String> customStopwordSet) {

		if (customStopwordSet == null) {
			customStopwordSet = stopwordSet;
			if (stopwordSet == null)
				return rawContent;
		}
		StringBuilder sb = new StringBuilder();
		for (String s : tokenizeString(rawContent)) {
			if (getStopwordCase())
				s = s.toLowerCase();
			if (!customStopwordSet.contains(s)) {
				sb.append(s);
				sb.append(' ');
			}
		}
		return sb.toString();
	}

	/**
	 * Replaces the string based on the map. Uses replace file if
	 * customReplaceMap is null
	 * 
	 * @param rawContent
	 * @param customReplaceMap
	 * @return
	 */
	public String replaceToken(String rawContent) {
		if (replaceTokenMap == null)
			return rawContent;

		StringBuilder sb = new StringBuilder();
		for (String s : tokenizeString(rawContent)) {
			if (getReplaceCase())
				s = s.toLowerCase();
			if (replaceTokenMap.keySet().contains(s)) {
				sb.append(replaceTokenMap.get(s));
				sb.append(' ');
			}
		}
		return sb.toString();
	}

	public String replacePhrase(String rawContent) {
		if (replacePhraseMap == null)
			return rawContent;
		String replacedString = rawContent;
		for (String regexKey : replacePhraseMap.keySet()) {
			replacedString = rawContent.replaceAll(regexKey,
					replacePhraseMap.get(regexKey));
		}

		return replacedString;
	}

	/**
	 * Finds the string between two search strings. To include search strings in
	 * the final string, set inclusive to true.
	 * 
	 * 
	 * @param sourceString
	 * @param beginString
	 * @param endString
	 * @param inclusive
	 * @return
	 */

	public List<String> getBoundingString(String sourceString,
			String beginString, String endString, boolean inclusive) {
		List<String> stringList = new ArrayList<String>();
		List<Span> beginSpans = StringUtils.getSpan(sourceString, beginString);
		List<Span> endSpans = StringUtils.getSpan(sourceString, endString);
		for (Span bs : beginSpans) {
			for (Span es : endSpans) {
				if (es.getEndIndex() <= bs.getBeginIndex())
					continue;
				if (inclusive)
					stringList.add(sourceString.substring(bs.getBeginIndex(),
							es.getEndIndex() + 1));
				else
					stringList.add(sourceString.substring(bs.getEndIndex() + 1,
							es.getBeginIndex()));

			}
		}
		return stringList;
	}

	public String removeRecurringCharacters(String string, char character) {
		String regexString = StringUtils.escapeRegex(character);
		return string.replaceAll(regexString + "+", character + "");
	}

	public String getNGramsString(String string, int n, char splitCharacter,
			char nGramDelimiter) {
		
		return string;

	}

	public static void main(String args[]) {
		System.out.println(new TextProcessor().removeRecurringCharacters(
				"Thissss\\\\\\\\   d", 's'));
	}

}
